package org.zjx.window.window;

import lombok.Getter;
import org.zjx.window.action.IAction;
import org.zjx.window.operation.WindowOperation;
import org.zjx.window.window.impl.VirtualWindow;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * 激活管理器
 * 统一管理窗口激活操作，确保多线程环境下的窗口激活顺序和资源协调
 *
 * @author zjx
 * @since 1.0
 */
public class ActivationManager {

    /**
     * 激活虚拟窗口单例
     */
    @Getter
    private static final VirtualWindow activationWindow = new VirtualWindow();

    /**
     * 私有构造方法，防止实例化
     */
    private ActivationManager() {
        throw new UnsupportedOperationException("激活管理器不能实例化");
    }

    /**
     * 同步执行需要激活权的动作（阻塞直到完成）
     *
     * @param action 要执行的动作，不能为null
     * @return 执行是否成功
     * @throws IllegalArgumentException 如果action为null
     */
    public static boolean executeWithActivation(IAction action) {
        Objects.requireNonNull(action, "动作不能为null");

        IWindow targetWindow = action.getTargetWindow();
        if (targetWindow == null) {
            System.err.println("动作未绑定目标窗口: " + action.getActionName());
            return false;
        }

        try {
            // 设置目标窗口并执行
            activationWindow.setTargetWindow(targetWindow);
            return activationWindow.executeWithActivationSync(action);
        } catch (Exception e) {
            System.err.println("激活执行失败 [" + action.getActionName() + "]: " + e.getMessage());
            return false;
        }
    }

    /**
     * 异步执行需要激活权的动作
     *
     * @param action 要执行的动作，不能为null
     * @return 异步执行结果Future，包含执行是否成功
     * @throws IllegalArgumentException 如果action为null
     */
    public static CompletableFuture<Boolean> executeWithActivationAsync(IAction action) {
        Objects.requireNonNull(action, "动作不能为null");

        IWindow targetWindow = action.getTargetWindow();
        if (targetWindow == null) {
            System.err.println("动作未绑定目标窗口: " + action.getActionName());
            return CompletableFuture.completedFuture(false);
        }

        try {
            activationWindow.setTargetWindow(targetWindow);
            return activationWindow.submitAction(action);
        } catch (Exception e) {
            System.err.println("激活执行提交失败 [" + action.getActionName() + "]: " + e.getMessage());
            return CompletableFuture.completedFuture(false);
        }
    }

    /**
     * 执行需要激活权的窗口操作（阻塞直到完成）
     *
     * @param operation 要执行的操作，不能为null
     * @param targetWindow 目标窗口，不能为null
     * @throws IllegalArgumentException 如果operation或targetWindow为null
     */
    public static void executeWithActivation(WindowOperation operation, IWindow targetWindow) {
        Objects.requireNonNull(operation, "窗口操作不能为null");
        Objects.requireNonNull(targetWindow, "目标窗口不能为null");

        try {
            activationWindow.setTargetWindow(targetWindow);
            activationWindow.executeWithActivationSync(operation);
        } catch (Exception e) {
            System.err.println("激活操作执行失败: " + e.getMessage());
        }
    }

    /**
     * 异步执行需要激活权的窗口操作
     *
     * @param operation 要执行的操作，不能为null
     * @param targetWindow 目标窗口，不能为null
     * @return 异步执行结果Future
     * @throws IllegalArgumentException 如果operation或targetWindow为null
     */
    public static CompletableFuture<Boolean> executeWithActivationAsync(WindowOperation operation, IWindow targetWindow) {
        Objects.requireNonNull(operation, "窗口操作不能为null");
        Objects.requireNonNull(targetWindow, "目标窗口不能为null");

        try {
            activationWindow.setTargetWindow(targetWindow);
            // 由于WindowOperation没有返回值的概念，这里包装一下
            return CompletableFuture.supplyAsync(() -> {
                activationWindow.executeWithActivationSync(operation);
                return true;
            });
        } catch (Exception e) {
            System.err.println("激活操作提交失败: " + e.getMessage());
            return CompletableFuture.completedFuture(false);
        }
    }

    /**
     * 检查激活管理器是否正在运行
     *
     * @return 如果激活管理器运行中返回true，否则返回false
     */
    public static boolean isRunning() {
        return activationWindow.isRunning();
    }

    /**
     * 获取激活队列大小
     *
     * @return 当前激活队列中的任务数量
     */
    public static int getActivationQueueSize() {
        return activationWindow.getActivationQueueSize();
    }

    /**
     * 等待激活队列清空
     *
     * @param timeout 超时时间
     * @param unit 时间单位
     * @return 如果在超时前队列清空返回true，否则返回false
     * @throws InterruptedException 如果等待过程中被中断
     */
    public static boolean waitForQueueEmpty(long timeout, TimeUnit unit) throws InterruptedException {
        Objects.requireNonNull(unit, "时间单位不能为null");

        long endTime = System.currentTimeMillis() + unit.toMillis(timeout);
        while (System.currentTimeMillis() < endTime) {
            if (activationWindow.getActivationQueueSize() == 0) {
                return true;
            }
            Thread.sleep(100);
        }
        return activationWindow.getActivationQueueSize() == 0;
    }

    /**
     * 关闭激活管理器并释放资源
     * 注意：关闭后需要重新初始化才能再次使用
     */
    public static void shutdown() {
        System.out.println("关闭激活管理器...");
        activationWindow.shutdown();

        try {
            // 等待激活窗口完全关闭
            if (!activationWindow.awaitTermination(10, TimeUnit.SECONDS)) {
                System.err.println("激活管理器关闭超时，强制终止");
            } else {
                System.out.println("激活管理器已关闭");
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.err.println("激活管理器关闭被中断");
        }
    }

    /**
     * 紧急关闭激活管理器（不等待任务完成）
     */
    public static void shutdownNow() {
        System.out.println("紧急关闭激活管理器...");
        activationWindow.shutdown();
    }

    /**
     * 重新初始化激活管理器
     * 用于在关闭后重新启用
     */
    public static void reinitialize() {
        if (activationWindow.isRunning()) {
            System.err.println("激活管理器仍在运行，无法重新初始化");
            return;
        }

        // 注意：这里实际上创建了新实例，但外部引用不变
        // 在实际使用中可能需要使用重置方法而不是重新创建
        System.out.println("重新初始化激活管理器");
        // VirtualWindow 实例是final的，无法替换，这里只是概念上的重新初始化
        // 实际使用时应该调用reset方法（如果VirtualWindow提供的话）
    }
}